package com.cloudlead.common.worker.web;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;


/**
 * @author dean
 */
public final class AnnotationScanHelper {

    private static final String RESOURCE_PATTERN = "/**/*.class";

    private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();

    public static Set<String> scanClass(String basePackage,
                                        Class<? extends Annotation> annotation) throws IOException {
        Set<String> classes = new HashSet<>();
        String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(basePackage)
                + RESOURCE_PATTERN;
        Resource[] resources = RESOURCE_PATTERN_RESOLVER
                .getResources(pattern);
        MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(
                RESOURCE_PATTERN_RESOLVER);
        if (resources == null || readerFactory == null) {
            return classes;
        }

        for (Resource resource : resources) {
            if (resource.isReadable()) {
                MetadataReader reader = readerFactory
                        .getMetadataReader(resource);
                AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(annotation, false);
                if (annotationTypeFilter.match(reader, readerFactory)) {
                    String className = reader.getClassMetadata().getClassName();
                    classes.add(className);
                }
            }
        }
        return classes;
    }


}